package in.muton.edushare.components.calendar;

import in.muton.edushare.common.VOHelper;
import in.muton.edushare.components.autocomplete.EdushareTextArea;
import in.muton.edushare.components.calendar.api.UniqueElementList;
import in.muton.edushare.components.calendar.api.CalendarInterface;
import in.muton.edushare.components.calendar.api.EventHelper;
import in.muton.edushare.components.calendar.api.PeopleManager;
import in.muton.edushare.pages.EduShareBasePage;
import in.muton.edushare.pages.common.EdusharePanel;
import in.muton.edushare.schedules.DateParser;
import in.muton.edushare.schedules.DeleteSchedule;
import in.muton.edushare.schedules.NewSchedule;
import in.muton.edushare.schedules.widgets.DateHelper;
import in.muton.edushare.wicket.converters.choicerenderers.FrequencyChoiceRenderer;
import in.muton.edushare.wicket.models.CayenneList;
import in.muton.edushare.wicket.models.CayenneModel;

import java.util.Arrays;
import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.HiddenField;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;

import com.edushare.common.dao.ScheduleDAO;
import com.edushare.common.util.StringUtil;
import com.edushare.common.vo.CourseInstances;
import com.edushare.common.vo.Departments;
import com.edushare.common.vo.Groups;
import com.edushare.common.vo.Messages;
import com.edushare.common.vo.ScheduleNotifications;
import com.edushare.common.vo.Schedules;
import com.edushare.common.vo.Universities;
import com.edushare.common.vo.Users;

public class EvtDialog extends EdusharePanel {
	private static final Log log = LogFactory.getLog(EvtDialog.class);
	private static final long serialVersionUID = 873648121692920838L;

	public EvtDialog(String id, Groups group, EduShareBasePage page) {
		super(id, page);
		this.creatorId = group.getGroupId();
		this.creatorType = Messages.RECEIVER_TYPE_GROUP;
		creatorModel = new CayenneModel<Object>(group);
		init();
	}

	public EvtDialog(String id, Departments dept, EduShareBasePage page) {
		super(id, page);
		this.creatorId = dept.getDepartmentId();
		this.creatorType = Messages.RECEIVER_TYPE_DEPARTMENT;
		creatorModel = new CayenneModel<Object>(dept);
		init();
	}

	public EvtDialog(String id, Universities univ, EduShareBasePage page) {
		super(id, page);
		this.creatorId = univ.getUniversityId();
		this.creatorType = Messages.RECEIVER_TYPE_UNIVERSITY;
		creatorModel = new CayenneModel<Object>(univ);
		init();
	}

	public EvtDialog(String id, CourseInstances inst, EduShareBasePage page) {
		super(id, page);
		this.creatorId = inst.getCourseInstanceId();
		this.creatorType = Messages.RECEIVER_TYPE_COURSE;
		creatorModel = new CayenneModel<Object>(inst);
		init();
	}

	public EvtDialog(String id, Users user, EduShareBasePage page) {
		super(id, page);
		this.creatorId = user.getUserId();
		this.creatorType = Messages.RECEIVER_TYPE_USER;
		creatorModel = new CayenneModel<Object>(user);
		this.userCalendar = true;
		init();
	}

	private void init() {
		Form<Void> newEvtDialog = new Form<Void>("newEventForm") {
			private static final long serialVersionUID = 1L;

			@Override
			public void onSubmit() {
				Schedules existingEvent = null;
				if (findSubmittingButton() == deleteButton) {
					return;
				}
				if (schId != null)
					existingEvent = CalendarInterface.getEventById(Integer
							.parseInt(schId));
				if (existingEvent != null
						&& EventHelper.isEditable(existingEvent,
								getLoggedInUser())) {
					updateExistingEvent(existingEvent);
				} else {
					addNewEvent();
				}
			}
		};

		add(newEvtDialog);
		setDefaultModel(new CompoundPropertyModel<EvtDialog>(this));
		newEvtDialog.setMarkupId("dateDialog").setOutputMarkupId(true);
		newEvtDialog.add(new TextArea<String>("schDesc").setMarkupId("schDesc")
				.setOutputMarkupId(true));
		newEvtDialog.add(new TextField<String>("schLocation").setMarkupId(
				"schLocation").setOutputMarkupId(true));
		newEvtDialog.add(new TextField<String>("schTitle").setMarkupId(
				"schTitle").setOutputMarkupId(true));
		newEvtDialog.add((new HiddenField<String>("schStart")).setMarkupId(
				"schStart").setOutputMarkupId(true));
		newEvtDialog.add((new HiddenField<String>("schEnd")).setMarkupId(
				"schEnd").setOutputMarkupId(true));
		newEvtDialog.add((new TextField<String>("repetitionEnd")).setMarkupId(
				"repetitionEnd").setOutputMarkupId(true));
		newEvtDialog.add(new HiddenField<String>("schId").setMarkupId("schId")
				.setOutputMarkupId(true));
		newEvtDialog.add(new EdushareTextArea("schPPL",
				new PropertyModel<String>(this, "schPPL")).setOutputMarkupId(
				true).setVisible(userCalendar));

		Integer[] frequencyArray = { Schedules.EVENT_ONCE_ONLY,
				Schedules.EVENT_DAILY, Schedules.EVENT_WEEKLY,
				Schedules.EVENT_MONTHLY };
		newEvtDialog.add((repetitionType = new DropDownChoice<Integer>(
				"frequency", Arrays.asList(frequencyArray),
				new FrequencyChoiceRenderer())));
		repetitionType.setMarkupId("frequency").setOutputMarkupId(true);

		deleteButton = new Button("delete") {
			private static final long serialVersionUID = 4339473452193487768L;
			@Override
			public void onSubmit() {
				log.debug("GetschDesc =" + getSchDesc());
				log.debug("GetschEnd =" + getSchEnd());
				log.debug("GetschStart =" + getSchStart());
				log.debug("GetschLocation =" + getSchLocation());
				log.debug("GetFrequency =" + getFrequency());
				log.debug("GetRepetitionEnd =" + getRepetitionEnd());
				log.debug("Event delete SchId = " + schId);
				Schedules existingEvent = CalendarInterface
						.getEventById(Integer.parseInt(schId));
				if (existingEvent != null
						&& EventHelper.isEditable(existingEvent,
								getLoggedInUser())) {
					log.debug("Deleting event");
					new DeleteSchedule(new Model<Schedules>(existingEvent))
							.delete();
					/*
					new ScheduleMessage(existingEvent,
							ScheduleMessage.EVT_CANCELLED).setReciever(
							VOHelper.getFromTypeId(existingEvent
									.getCreatorType(), existingEvent
									.getSchCreator())).setPrivacy(
							Messages.PRIVACY_TYPE_PUBLIC).send();
					*/
				} else if (existingEvent == null) {
					log.debug("Could not find event to delete.");
				} else {
					log.debug("Access control problems while deleting event.");
				}
			}
		};
		deleteButton.setOutputMarkupId(true).setMarkupId("delete");
		newEvtDialog.add(deleteButton);
	}

	private void updateExistingEvent(Schedules sch) {
		setError("");
		String s = sch.getSchTitle();
		if (!fillDataInSch(sch))
			return;

		String error = PeopleManager.cleanConvert(schPPL);
		if (error.length() > 0) {
			setError(error);
			return;
		}

		Object o = VOHelper.getFromTypeId(sch.getCreatorType(), sch
				.getSchCreator());
		ScheduleDAO schDAO = new ScheduleDAO(getORMInterface());
		schDAO.clearNotifications(sch);
		UniqueElementList<Users> userList = new UniqueElementList<Users>(null);
		CayenneList<Users> l = VOHelper.getVOUsers(o);
		userList.add(l);
		userList.add(PeopleManager.getUsers(schPPL));
		schDAO.sendNotifications(sch, userList.getObject(),
				ScheduleNotifications.OPEN);
		/*
		 * new ScheduleMessage(sch, s, ScheduleMessage.EVT_MODIFY).setReciever(o)
		 
				.setReciever(userList).setPrivacy(Messages.PRIVACY_TYPE_PUBLIC)
				.send();
		 */
		getORMInterface().commitAllChanges();
	}

	private void addNewEvent() {
		setError("");
		Schedules sch = new Schedules();
		sch.setCreatingUser(getLoggedInUser());
		sch.setCreationTimestamp(new Date());
		if (!fillDataInSch(sch))
			return;
		if (DateHelper.after(sch.getSchEnd(), sch.getSchStart())) {
			sch.setRepetitionEnd(sch.getSchEnd());
			sch.setFrequency(Schedules.EVENT_DAILY);
		}

		String s = PeopleManager.cleanConvert(schPPL);
		if (s.length() > 0) {
			setError(s);
			return;
		}

		log.debug("Schedules initialised");
		Object o = VOHelper.getFromTypeId(creatorType, creatorId);
		CayenneList<Users> list = VOHelper.getVOUsers(o);
		UniqueElementList<Users> userList = new UniqueElementList<Users>(null);
		userList.add(list);
		userList.add(PeopleManager.getUsers(schPPL));
		new NewSchedule(sch, creatorModel.getObject(), creatorType, creatorId,
				userList.getUtilList()).send();
		/*ScheduleDAO sDAO = new ScheduleDAO(getORMInterface());
		  new ScheduleMessage(sch, ScheduleMessage.NEW_EVENT).setReciever(
				VOHelper.getFromTypeId(sch.getCreatorType(), sch
						.getSchCreator())).setReciever(
				new CayenneList<Users>(sDAO.getRecievers(sch))).setPrivacy(
				Messages.PRIVACY_TYPE_PUBLIC).send();
		*/
		getORMInterface().commitAllChanges();
	}

	public boolean fillDataInSch(Schedules sch) {
		try {
			if (!StringUtil.isValid(getSchStart())
					|| !StringUtil.isValid(getSchEnd())) {
				setError("Starting and ending times are required.");
				return false;
			}
			if (!StringUtil.isValid(getRepetitionEnd())) {
				setError("Repetition end time is required");
				return false;
			}
			Date schStartT = DateParser.getDate(schStart);
			Date schEndT = DateParser.getDate(schEnd);
			Date repetitionEndDateT = DateParser.getDateOnly(repetitionEnd);
			if (schStartT.getTime() > schEndT.getTime()) {
				setError("The starting time must be less than the ending time.");
				return false;
			} else if (schStartT.getTime() > repetitionEndDateT.getTime()
					&& getFrequency() != Schedules.EVENT_ONCE_ONLY) {
				setError("The repetition end time must be greater than the start time.");
				return false;
			} else if (schStartT.getTime() < new Date().getTime()) {
				setError("The event must start in the future");
				return false;
			} else if (!StringUtil.isValid(schTitle)) {
				setError("Event title is required.");
				return false;
			}
			sch.setUpdatedTimestamp(new Date());
			sch.setSchDesc(getSchDesc());
			sch.setSchEnd(DateParser.getDate(getSchEnd()));
			sch.setSchStart(DateParser.getDate(getSchStart()));
			sch.setSchLocation(getSchLocation());
			sch.setSchTitle(getSchTitle());
			sch.setSchType(0);
			sch.setFrequency(getFrequency());
			sch.setRepetitionEnd(DateParser.getDateOnly(getRepetitionEnd()));
			sch.setStatus(Schedules.EVENT_STATUS_OPEN);
		} catch (Exception e) {
			setError("An unknown error has occured. Your schedule has not been set. Please try again.");
			return false;
		}
		return true;
	}

	public void setSchId(String schId) {
		this.schId = schId;
	}

	public String getSchId() {
		return schId;
	}

	public void setSchStart(String schStart) {
		this.schStart = schStart;
	}

	public String getSchStart() {
		return schStart;
	}

	public void setSchEnd(String schEnd) {
		this.schEnd = schEnd;
	}

	public String getSchEnd() {
		return schEnd;
	}

	public void setSchTitle(String schTitle) {
		this.schTitle = schTitle;
	}

	public String getSchTitle() {
		return schTitle;
	}

	public void setSchLocation(String schLocation) {
		this.schLocation = schLocation;
	}

	public String getSchLocation() {
		return schLocation;
	}

	public void setFrequency(Integer frequency) {
		this.frequency = frequency;
	}

	public Integer getFrequency() {
		return frequency;
	}

	public void setRepetitionEnd(String repetitionEnd) {
		this.repetitionEnd = repetitionEnd;
	}

	public String getRepetitionEnd() {
		return repetitionEnd;
	}

	public void setSchDesc(String schDesc) {
		this.schDesc = schDesc;
	}

	public String getSchDesc() {
		return schDesc;
	}

	public String getSchPPL() {
		return schPPL;
	}

	public void setSchPPL(String schPPL) {
		this.schPPL = schPPL;
	}

	private Integer creatorId = 0;
	private Integer creatorType = 0;
	private IModel<Object> creatorModel = null;

	private Button deleteButton = null;

	private String schPPL = "";
	private String schId = "";
	private String schStart = "";
	private String schEnd = "";
	private String schTitle = "";
	private String schLocation = "";
	private Integer frequency = 0;
	private String repetitionEnd = "";
	private String schDesc = "";
	private DropDownChoice<Integer> repetitionType;
	private boolean userCalendar = true;
}
